package com.syg.Commons.Filter;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.Enumeration;

public class XssRequestWrapper extends HttpServletRequestWrapper {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private String requestBody = null;//因为request中的数据只能读取一次,故此采用——>取出重新放入的方式

    private HttpServletRequest req;//传进来的request(是真正的request,所以我们从这里获取数据)

    /**
     * 父类没有无参构造,子类肯定也没有无参构造
     * 1,首先调用这个方法创建对象
     *
     * @param request
     */
    public XssRequestWrapper(HttpServletRequest request) {
        super(request);
        this.req = request;//将传进来的request赋给我们声明的变量
    }

    @Override
    public String getHeader(String name) {
        String value = super.getHeader(name);
        logger.info("这个方法什么时候打印");
        return scriptXSS(value);
    }

    /**
     * 获取get方式的请求字符串(get请求没有请求体)
     *
     * @return
     */
    @Override
    public String getQueryString() {
        logger.info("这个方法会打印几次,什么时候打印");
        return scriptXSS(super.getQueryString());
    }

    /**
     * 当请求体内容类型是:application/x- www-form-urlencoded(POST和form表单的默认请求类型),
     * 对该类型的请求内容提供了request.getParameter()方法来获取请求参数值(getReader(),getInputStream()应该也是可以的,三个方法互斥)
     *
     * @param name
     * @return
     */
    @Override
    public String getParameter(String name) {
        String value = super.getParameter(name);
        logger.info("我就想知道这个方法会打印几次,什么时候打印");
        return scriptXSS(value);
    }

    /**
     * 当请求体内容类型非:application/x- www-form-urlencoded
     * request.getInputStream()或request.getReader()方法来获取请求内容
     *
     * @return
     * @throws IOException
     */
    @Override
    public BufferedReader getReader() throws IOException {
        return new BufferedReader(new StringReader(requestBody));
    }

    /**
     * 当请求体内容非:application/x-www-form-urlencoded
     * request.getInputStream()或request.getReader()方法获取请求内容
     *
     * @return
     * @throws IOException
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        return new ServletInputStream() {
            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener listener) {

            }

            private InputStream in = new ByteArrayInputStream(requestBody.getBytes(req.getCharacterEncoding()));

            @Override
            public int read() throws IOException {
                return in.read();
            }
        };
    }


    @Override
    public Enumeration<String> getParameterNames() {
        return super.getParameterNames();
    }

    /**
     * 2,在过滤器中调用执行
     */
    public void filterXSS() {
        String reqContent = this.getRequestBody();//获取请求体内容
        this.requestBody = scriptXSS(reqContent);//过滤XSS请求

    }

    /**
     * 防XSS攻击
     *
     * @param value
     * @return
     */
    private String scriptXSS(String value) {
        if (null != value) {
            return value.replaceAll("<", "shenyiguang").replaceAll(">", "shenyiguang");
        }
        return value;
    }

    /**
     * 获取请求体数据(get请求没有请求体),在filterXSS()调用
     *
     * @return
     */
    private String getRequestBody() {
        try {
            BufferedReader reader = req.getReader();
            StringBuffer stringBuffer = new StringBuffer();
            String line;
            while ((line = reader.readLine()) != null) {
                stringBuffer.append(line);
            }
            String jsonStr = stringBuffer.toString();
            return jsonStr;
        } catch (IOException e) {
            logger.info("getRequestBody()Exception===>", e);
        }
        return "";
    }
}
